package com.qd.extcamclientv2;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.hardware.SensorManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class SensorView extends View {
	private static final String TAG = "SensorView";
	private final static int MAX_DEGREE = 120;

	private float mAzimuth = 0;	// 방위각
	private float mPitch = 0;	// 상하 기울기
	private float mRoll = 0;	// 좌우 기울기

	private Paint mPaint = new Paint();
	private Paint mPaintText = new Paint();
	private Rect mRectPitch = new Rect();
	private Rect mRectRoll = new Rect();
	private Bitmap mBitmapComapss = null;
	private int mThick;
	private Matrix mMatrix = new Matrix();

	/**
	 * @param context
	 * @param attrs
	 * @param defStyle
	 */
	public SensorView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		init();
	}

	/**
	 * @param context
	 * @param attrs
	 */
	public SensorView(Context context, AttributeSet attrs) {
		super(context, attrs);

		init();
	}

	/**
	 * @param context
	 */
	public SensorView(Context context) {
		super(context);

		init();
	}

	/**
	 * 
	 */
	private void init() {
		mPaint.setAntiAlias(true);
		mPaintText.setColor(Color.BLACK);
		mPaintText.setTextSize(20);
		mPaintText.setAntiAlias(true);
	}

	/* (non-Javadoc)
	 * @see android.view.View#onSizeChanged(int, int, int, int)
	 */
	public void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		Log.e(TAG, "onSizeChanged(" + w + ", " + h + ", " + oldw + ", " + oldh + ")");

		if (w > h) {
			mThick = h / 10;
		} else {
			mThick = w / 10;
		}
		int length = mThick * 6;

		mRectPitch.set(mThick, mThick, mThick*2, mThick + length);
		mRectRoll.set(mThick, mThick*2 + length, mThick*9, mThick*2 + length + mThick);

		Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.compass);
		mBitmapComapss = Bitmap.createScaledBitmap(bitmap, mThick*6, mThick*6, false);
	}

	/* (non-Javadoc)
	 * @see android.view.View#onDraw(android.graphics.Canvas)
	 */
	public void onDraw(Canvas canvas) {
		// 수평, 수직 막대기 그림
		canvas.drawColor(Color.WHITE);
		mPaint.setColor(Color.BLACK);
		canvas.drawRect(mRectPitch, mPaint);
		canvas.drawRect(mRectRoll, mPaint);

		// 롤 값 표시
		float rollvalue = mRoll < -MAX_DEGREE ? -MAX_DEGREE : (mRoll > MAX_DEGREE ? MAX_DEGREE : mRoll);
		int rollcenter = mRectRoll.left + mRectRoll.width()/2;
		int rolllength = mRectRoll.width() - mThick;
		int rollpos = rollcenter + (int)(rolllength/2 * rollvalue / MAX_DEGREE);
		mPaint.setColor(rollvalue == 0 ? Color.RED:Color.YELLOW);
		canvas.drawCircle(rollpos, mRectRoll.top + mThick/2, (int)(mThick/2*0.9), mPaint);
		//canvas.drawText("roll:" + (int)mRoll, mRectRoll.left, mRectRoll.top-5, mPaintText);

		// 피치값 표시
		float pitchvalue = mPitch;
		if ((Math.abs(mPitch)) > 90) {
			pitchvalue = 180 - Math.abs(mPitch);
			if (mPitch < 0) pitchvalue *= -1; 
		}
		pitchvalue = pitchvalue < -MAX_DEGREE ? -MAX_DEGREE : (pitchvalue > MAX_DEGREE ? MAX_DEGREE : pitchvalue);
		int pitchcenter = mRectPitch.top + mRectPitch.height()/2;
		int pitchlength = mRectPitch.height() - mThick;
		int pitchpos = pitchcenter + (int)(pitchlength/2 * pitchvalue / MAX_DEGREE);
		mPaint.setColor(pitchvalue == 0 ? Color.RED:Color.YELLOW);
		canvas.drawCircle(mRectPitch.left + mThick/2, pitchpos, (int)(mThick/2*0.9), mPaint);
		//canvas.drawText("pitch:" + (int)mPitch, mRectPitch.left, mRectPitch.top-5, mPaintText);

		// 나침반 표시
		mMatrix.postRotate(-mAzimuth, mBitmapComapss.getWidth()/2, mBitmapComapss.getHeight()/2);
		mMatrix.postTranslate(rollcenter - mBitmapComapss.getWidth()/2 + mThick, pitchcenter - mBitmapComapss.getHeight()/2);
		canvas.drawBitmap(mBitmapComapss, mMatrix, mPaint);
		//canvas.drawText("azimuth:" + (int)mAzimuth, rollcenter, pitchcenter - mBitmapComapss.getHeight()/2 - 5, mPaintText);
		mMatrix.reset();
	}

	/**
	 * @param azimuth
	 * @param pitch
	 * @param roll
	 * @param x
	 * @param y
	 * @param z
	 */
	public void setData(float azimuth, float pitch, float roll, float x, float y, float z) {
		mAzimuth = azimuth;
		mPitch = pitch;
		mRoll = roll;
		invalidate();
	}
}


class AcceleratorView extends View {
	private final static float G = SensorManager.STANDARD_GRAVITY;
	private final static int MAGX = 5;
	private final static int MAGY = 2;

	private int mWidth;
	private int mHeight;
	private int mWidth10;
	private ArrayList<AccelValue> mAccelList = new ArrayList<AccelValue>();
	private boolean mArrange = true;
	private Paint mPaint = new Paint();
	private Paint mPaintLine = new Paint();
	private int mType = 1;

	/**
	 * @param context
	 * @param attrs
	 * @param defStyle
	 */
	public AcceleratorView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		init();
	}

	/**
	 * @param context
	 * @param attrs
	 */
	public AcceleratorView(Context context, AttributeSet attrs) {
		super(context, attrs);

		init();
	}

	/**
	 * @param context
	 */
	public AcceleratorView(Context context) {
		super(context);

		init();
	}

	/**
	 * 
	 */
	private void init() {
		mPaint.setColor(Color.YELLOW);
		mPaint.setTextSize(20);
		mPaint.setStrokeWidth(2);
		//mPaint.setStyle(Paint.Style.STROKE);

		mPaintLine.setColor(Color.WHITE);
		mPaintLine.setStrokeWidth(1);
		mPaintLine.setStyle(Paint.Style.STROKE);
	}

	/* (non-Javadoc)
	 * @see android.view.View#onSizeChanged(int, int, int, int)
	 */
	public void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		mWidth = w;
		mHeight = h;
		mWidth10 = mWidth / 10;
	}

	/* (non-Javadoc)
	 * @see android.view.View#onTouchEvent(android.view.MotionEvent)
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mType = (mType + 1) % 2;
			break;
		case MotionEvent.ACTION_MOVE:
			break;
		case MotionEvent.ACTION_UP:
			break;
		}

		return super.onTouchEvent(event);
	}

	/* (non-Javadoc)
	 * @see android.view.View#onDraw(android.graphics.Canvas)
	 */
	public void onDraw(Canvas canvas) {
		int i;
		AccelValue v;
		float value;
		int x=0, y=0;
		int oldx, oldy;
		int basex;

		// X 가속 그림
		basex = oldx = mWidth10 * 2;
		if (0 == mType) {
			oldy = 0;
			canvas.drawText("X", basex - 25, 25, mPaint);
			canvas.drawLine(basex, 0, basex, mHeight, mPaintLine);
			for (i=0; i<mAccelList.size(); i++) {
				v = mAccelList.get(i);
				value = v.x;
				if (mArrange) {
					value -= (float)Math.sin(Deg2Rad(v.roll)) * G;
				}
				x = (int)(basex + value * MAGX);
				y = i * MAGY;
				canvas.drawLine(oldx, oldy, x, y, mPaint);
				oldx = x;
				oldy = y;
			}
		} else if (1 == mType) {
			if (0 < mAccelList.size()) {
				v = mAccelList.get(mAccelList.size()-1);
				value = v.x;
				value -= (float)Math.sin(Deg2Rad(v.roll)) * G;
				x = (int)(basex + value * 10);
				y = mHeight / 2;
				canvas.drawLine(basex, 0, x, y, mPaintLine);
				canvas.drawLine(basex, mHeight, x, y, mPaintLine);
				canvas.drawCircle(x, y, mWidth10/3, mPaint);
			}
		}

		// Y 가속 그림
		basex = oldx = mWidth10 * 5;
		if (0 == mType) {
			oldy = 0;
			canvas.drawText("Y", basex - 25, 25, mPaint);
			canvas.drawLine(basex, 0, basex, mHeight, mPaintLine);
			for (i=0; i<mAccelList.size(); i++) {
				v = mAccelList.get(i);
				value = v.y;
				if (mArrange) {
					value += (float)Math.sin(Deg2Rad(v.pitch)) * G;
				}
				x = (int)(basex + value * MAGX);
				y = i * MAGY;
				canvas.drawLine(oldx, oldy, x, y, mPaint);
				oldx = x;
				oldy = y;
			}
		} else if (1 == mType) {
			if (0 < mAccelList.size()) {
				v = mAccelList.get(mAccelList.size()-1);
				value = v.y;
				value += (float)Math.sin(Deg2Rad(v.pitch)) * G;
				y = (mHeight / 2) + (int)(value * 10);
				canvas.drawLine(mWidth10*4, mHeight/2, basex, y, mPaintLine);
				canvas.drawLine(mWidth10*6, mHeight/2, basex, y, mPaintLine);
				canvas.drawCircle(basex, y, mWidth10/3, mPaint);
			}
		}

		// Z 가속 그림
		basex = oldx = mWidth10 * 8;
		if (0 == mType) {
			oldy = 0;
			canvas.drawText("Z", basex - 25, 25, mPaint);
			canvas.drawLine(basex, 0, basex, mHeight, mPaintLine);
			for (i=0; i<mAccelList.size(); i++) {
				v = mAccelList.get(i);
				value = v.z;
				if (mArrange) {
					// 중력을 제외한 순수한 Z 축 움직임을 구하는 방법을 아직 찾지 못했음
					// pitch, roll을 알고 있지만 방정식을 도출할 수 없음
				}
				x = (int)(basex + value * MAGX);
				y = i * MAGY;
				canvas.drawLine(oldx, oldy, x, y, mPaint);
				oldx = x;
				oldy = y;
			}
		} else if (1 == mType) {
			if (0 < mAccelList.size()) {
				v = mAccelList.get(mAccelList.size()-1);
				value = v.z;
				y = (mWidth10 / 2) + (int)(value * 10);
				canvas.drawLine(mWidth10*7, mHeight/2, mWidth10*9, mHeight/2, mPaintLine);
				canvas.drawLine(mWidth10*8, 0, mWidth10*8, mHeight, mPaintLine);
				canvas.drawCircle(basex, (mHeight / 2), y, mPaint);
			}
		}
	}

	/**
	 * @param deg
	 * @return
	 */
	private float Deg2Rad(float deg) {
		return (deg * (float)Math.PI) / 180;
	}

	/**
	 * @param azimuth
	 * @param pitch
	 * @param roll
	 * @param x
	 * @param y
	 * @param z
	 */
	public void setData(float azimuth, float pitch, float roll, float x, float y, float z) {
		if (mAccelList.size() * MAGY > mHeight - 10) {
			mAccelList.remove(0);
		}

		AccelValue acc = new AccelValue();
		acc.pitch = pitch;
		acc.roll = roll;
		acc.x = x;
		acc.y = y;
		acc.z = z;
		mAccelList.add(acc);

		invalidate();
	}

	private class AccelValue {
		float pitch;
		float roll;
		float x;
		float y;
		float z;
	}
}